package com.kgcx.coupon.service;

import com.alibaba.fastjson.JSON;
import com.kgcx.common.exception.BusinessException;
import com.kgcx.common.exception.CoreErrors;
import com.kgcx.common.log.Log;
import com.kgcx.coupon.constant.CouponCode;
import com.kgcx.coupon.domain.Advert;
import com.kgcx.coupon.dto.AdvertDTO;
import com.kgcx.coupon.enums.AdPlaceEnum;
import com.kgcx.coupon.enums.AdStatusEnum;
import com.kgcx.coupon.mapper.AdvertMapper;
import com.kgcx.coupon.vo.ad.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @author panjin.
 * @date 2017/12/15.
 */
@Service
@Slf4j
public class AdvertService {

    @Resource
    private AdvertMapper advertMapper;

    /**
     * 添加广告
     * @param advertReqVO 广告请求实体对象
     */
    public void add(AdvertReqVO advertReqVO) {
        Advert advert = new Advert();
        try {
            BeanUtils.copyProperties(advertReqVO, advert);
            advert.setImageAddress(JSON.toJSONString(advertReqVO.getAdImageList()));
            advert.setCreateTime(new Date());
            advert.setUpdateId(advertReqVO.getCreateId());
        } catch (Exception e) {
            log.error(Log.op("add").msg("参数转化异常").toString(), e);
            throw new BusinessException(CoreErrors.PARAM_ILLEGAL.getCode(), CoreErrors.PARAM_ILLEGAL.getMessage());
        }
        dataCheck(advert);
        advertMapper.insertSelective(advert);
    }

    /**
     * 分页查询广告列表
     * @param adVertQueryReqVO 广告查询请求对象
     * @return
     */
    public List<AdVertQueryRespVO> queryListWithPage(AdVertQueryReqVO adVertQueryReqVO) {
        return advertMapper.queryList(adVertQueryReqVO);
    }

    /**
     * 根据主键查询广告信息
     * @param kid 广告主键
     * @return
     */
    public AdvertRespVO queryAdvert(Integer kid) {
        Advert advert = advertMapper.selectByPrimaryKey(kid);
        if (null == advert) {
            throw new BusinessException(CouponCode.AD_NOT_EXISTS.getCode(), CouponCode.AD_NOT_EXISTS.getMessage());
        }
        AdvertRespVO advertRespVO = new AdvertRespVO();
        BeanUtils.copyProperties(advert, advertRespVO);
        List<AdImage> list = JSON.parseArray(advert.getImageAddress(), AdImage.class);
        advertRespVO.setAdImageList(list);
        return advertRespVO;
    }

    /**
     * 客户端获取广告
     * @param place 广告位
     * @return 如果不存在则返回null
     */
    public List<AdImage> getAdvert(Byte place) {

        if (null == AdPlaceEnum.getEnum(place)) {
            throw new BusinessException(CouponCode.UNSUPPORTED_AD_PLACE.getCode(), CouponCode.UNSUPPORTED_AD_PLACE.getMessage());
        }
        AdvertDTO advertDTO = new AdvertDTO();
        advertDTO.setCurrentTime(new Date());
        advertDTO.setPlace(place);
        advertDTO.setStatus(AdStatusEnum.ENABLED.getCode());
        List<Advert> advertList = advertMapper.selectAdvert(advertDTO);
        if (advertList.isEmpty()) {
            log.info(Log.op("getAdvert").msg("query is null").kv("place", place).toString());
            return null;
        }
        String imageAddress = advertList.get(0).getImageAddress();
        if (StringUtils.isBlank(imageAddress)) {
            log.info(Log.op("getAdvert").msg("imageAddress is blank").kv("place", place).toString());
            return null;
        }
        return JSON.parseArray(imageAddress, AdImage.class);
    }

    /**
     * 更新广告
     * @param advertUpdateReqVO 更新广告实体
     */
    public void updateAdvert(AdvertUpdateReqVO advertUpdateReqVO) {
        Advert advert = new Advert();
        try {
            BeanUtils.copyProperties(advertUpdateReqVO, advert);
            if (null != advertUpdateReqVO.getAdImageList()) {
                advert.setImageAddress(JSON.toJSONString(advertUpdateReqVO.getAdImageList()));
            }
            advert.setUpdateId(advertUpdateReqVO.getUpdateId());
        } catch (Exception e) {
            log.error(Log.op("update").msg("参数转化异常").toString(), e);
            throw new BusinessException(CoreErrors.PARAM_ILLEGAL.getCode(), CoreErrors.PARAM_ILLEGAL.getMessage());
        }
        dataCheck(advert);
        advertMapper.updateByPrimaryKeySelective(advert);
    }

    /**
     * 删除单条数据
     * @param kid 主键
     */
    public void deleteAdvert(Integer kid) {
        int total = advertMapper.deleteByPrimaryKey(kid);
        if (0==total) {
            log.warn(Log.op("deleteAdvert").msg("data not exist").kv("kid", kid).toString());
            throw new BusinessException(CouponCode.AD_NOT_EXISTS.getCode(), CouponCode.AD_NOT_EXISTS.getMessage());
        }
    }

    /**
     * 批量删除数据
     * @param kids 主键列表
     */
    public void deleteAdvertBatch(List<Integer> kids) {
        int total = advertMapper.deleteByPrimaryKeyBatch(kids);
        if (0==total) {
            log.warn(Log.op("deleteAdvertBatch").msg("data not exist").kv("kid", kids).toString());
            throw new BusinessException(CouponCode.AD_NOT_EXISTS.getCode(), CouponCode.AD_NOT_EXISTS.getMessage());
        }
    }

    /**
     * 广告数据校验
     * @param advert 广告实体
     */
    private void dataCheck(Advert advert) {
        if (advert.getEffectiveEndTime().before(advert.getEffectiveStartTime())) {
            throw new BusinessException(CoreErrors.PARAM_ILLEGAL.getCode(), "有效期结束时间不能小于开始时间");
        }
        AdVertQueryReqVO adVertQueryReqVO = new AdVertQueryReqVO();
        adVertQueryReqVO.setPlace(advert.getPlace());
        List<AdVertQueryRespVO> adVertQueryRespVOList = advertMapper.queryList(adVertQueryReqVO);
        for (AdVertQueryRespVO adVertQueryRespVO : adVertQueryRespVOList) {
            if (AdStatusEnum.ENABLED.getCode() == adVertQueryRespVO.getStatus()) {
                if (advert.getEffectiveStartTime().after(adVertQueryRespVO.getEffectiveStartTime())
                        && advert.getEffectiveStartTime().before(adVertQueryRespVO.getEffectiveEndTime())) {
                    log.warn(Log.op("").msg("开始时间重叠").kv("请求时间", advert.getEffectiveStartTime())
                            .kv("数据库开始时间", adVertQueryRespVO.getEffectiveStartTime())
                            .kv("数据库结束时间", adVertQueryRespVO.getEffectiveEndTime()).toString());
                    throw CouponCode.AD_EFFECTIVE_START_TIME.exp(adVertQueryRespVO.getName());
                }
                if (advert.getEffectiveEndTime().after(adVertQueryRespVO.getEffectiveStartTime())
                        && advert.getEffectiveEndTime().before(adVertQueryRespVO.getEffectiveEndTime())) {
                    log.warn(Log.op("").msg("结束时间重叠").kv("请求时间", advert.getEffectiveEndTime())
                            .kv("数据库开始时间", adVertQueryRespVO.getEffectiveStartTime())
                            .kv("数据库结束时间", adVertQueryRespVO.getEffectiveEndTime()).toString());
                    throw CouponCode.AD_EFFECTIVE_END_TIME.exp(adVertQueryRespVO.getName());
                }
            }
        }
    }
}
